package com.ruoyi.system.service.impl;

import com.ruoyi.system.domain.PublicOpinionEvents;
import com.ruoyi.system.domain.PublicOpinionTopic;
import com.ruoyi.system.domain.WarningRule;
import com.ruoyi.system.service.ElasticsearchQueryBuilderService;
import com.ruoyi.system.util.KeyWordUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

@Service
public class ElasticsearchQueryBuilderServiceImpl implements ElasticsearchQueryBuilderService {


    @Override
    public BoolQueryBuilder boolQueryBuilder(BoolQueryBuilder matchQueryBuilder, String searchArea, String relatedWords, String opinionWords, String exclusionWords) {

        if (matchQueryBuilder == null) {
            matchQueryBuilder = QueryBuilders.boolQuery();
        }

        if (searchArea.equals("all")) {
            boolean hasOr = relatedWords.contains(",");
            List<String> keys;
            if (hasOr) {
                keys = KeyWordUtils.transformationOr(relatedWords);
                BoolQueryBuilder sholdQueryBuilder = QueryBuilders.boolQuery();
                keys.forEach(s -> {
                    sholdQueryBuilder.should(QueryBuilders.queryStringQuery("\"" + s + "\"")
                            .field("content")
                            .field("title")
                            .defaultOperator(Operator.AND)
                            .minimumShouldMatch("1"));
                });
                matchQueryBuilder.must(sholdQueryBuilder);
            } else {
                keys = KeyWordUtils.transformationAnd(relatedWords);
                BoolQueryBuilder finalMatchQueryBuilder1 = matchQueryBuilder;
                keys.forEach(s -> {
                    finalMatchQueryBuilder1.must(QueryBuilders.queryStringQuery("\"" + s + "\"")
                            .field("content")
                            .field("title")
                            .defaultOperator(Operator.AND)
                            .minimumShouldMatch("1"));
                });

            }
            //舆情词
            if (StringUtils.isNotEmpty(opinionWords)) {
                matchQueryBuilder.must(QueryBuilders.multiMatchQuery(opinionWords, "title", "content"));
            }
            //排除词
            if (StringUtils.isNotEmpty(exclusionWords)) {
                matchQueryBuilder.mustNot(QueryBuilders.matchQuery("title", exclusionWords));
                matchQueryBuilder.mustNot(QueryBuilders.matchQuery("content", exclusionWords));
            }
        } else if (searchArea.equals("title")) {
            boolean hasOr = relatedWords.contains(",");
            List<String> keys;
            if (hasOr) {
                keys = KeyWordUtils.transformationOr(relatedWords);
                BoolQueryBuilder sholdQueryBuilder = QueryBuilders.boolQuery();
                keys.forEach(s -> {
                    sholdQueryBuilder.should(QueryBuilders.queryStringQuery("\"" + s + "\"")
                            .field("title")
                    );
                });
                matchQueryBuilder.must(sholdQueryBuilder);
            } else {
                keys = KeyWordUtils.transformationAnd(relatedWords);
                BoolQueryBuilder finalMatchQueryBuilder = matchQueryBuilder;
                keys.forEach(s -> {
                    finalMatchQueryBuilder.must(QueryBuilders.queryStringQuery("\"" + s + "\"")
                            .field("title")
                    );
                });

            }
            //舆情词
            if (StringUtils.isNotEmpty(opinionWords)) {
                matchQueryBuilder.must(QueryBuilders.matchQuery("title", opinionWords));
            }
            //排除词
            if (StringUtils.isNotEmpty(exclusionWords)) {
                matchQueryBuilder.mustNot(QueryBuilders.matchQuery("title", exclusionWords));
            }
        } else if (searchArea.equals("content")) {
            boolean hasOr = relatedWords.contains(",");
            List<String> keys;
            if (hasOr) {
                keys = KeyWordUtils.transformationOr(relatedWords);
                BoolQueryBuilder sholdQueryBuilder = QueryBuilders.boolQuery();
                keys.forEach(s -> {
                    sholdQueryBuilder.should(QueryBuilders.queryStringQuery("\"" + s + "\"")
                            .field("content")
                    );
                });
                matchQueryBuilder.must(sholdQueryBuilder);
            } else {
                keys = KeyWordUtils.transformationAnd(relatedWords);
                BoolQueryBuilder finalMatchQueryBuilder2 = matchQueryBuilder;
                keys.forEach(s -> {
                    finalMatchQueryBuilder2.must(QueryBuilders.queryStringQuery("\"" + s + "\"")
                            .field("content")
                    );
                });

            }
            //舆情词
            if (StringUtils.isNotEmpty(opinionWords)) {
                matchQueryBuilder.must(QueryBuilders.matchQuery("content", opinionWords));
            }
            //排除词
            if (StringUtils.isNotEmpty(exclusionWords)) {
                matchQueryBuilder.mustNot(QueryBuilders.matchQuery("content", exclusionWords));
            }
        }
        return matchQueryBuilder;
    }

    @Override
    public BoolQueryBuilder boolQueryBuilder(BoolQueryBuilder matchQueryBuilder, String searchArea, String relatedWords, String opinionWords, String exclusionWords, Date startTime, Date endTime) {
        if (startTime != null && endTime != null) {
            matchQueryBuilder = boolQueryBuilder(matchQueryBuilder, startTime, endTime);
        } else if (startTime != null) {
            matchQueryBuilder = boolQueryBuilderStartTime(matchQueryBuilder, startTime);
        } else if (endTime != null) {
            matchQueryBuilder = boolQueryBuilderEndTime(matchQueryBuilder, endTime);
        }
        return boolQueryBuilder(matchQueryBuilder, searchArea, relatedWords, opinionWords, exclusionWords);
    }

    @Override
    public BoolQueryBuilder boolQueryBuilder(PublicOpinionTopic topic) {
        return boolQueryBuilder(null, topic.getSearchArea(), topic.getRelatedWords(), topic.getOpinionWords(), topic.getExclusionWords());
    }

    /**
     * 构建舆情检索的开始时间
     *
     * @param startTime
     * @return
     */
    @Override
    public BoolQueryBuilder boolQueryBuilderStartTime(BoolQueryBuilder matchQueryBuilder, Date startTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        if (startTime != null) {
            sdf.setTimeZone(TimeZone.getTimeZone("GMT+8")); // 设置时区为东八区
            String beginPublishDayString = sdf.format(startTime);
            matchQueryBuilder.must(QueryBuilders.rangeQuery("publishTime")
                    .from(beginPublishDayString));
        }
        return matchQueryBuilder;
    }

    /**
     * 构建舆情检索的结束时间
     *
     * @param endTime
     * @return
     */
    @Override
    public BoolQueryBuilder boolQueryBuilderEndTime(BoolQueryBuilder matchQueryBuilder, Date endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        if (endTime != null) {
            sdf.setTimeZone(TimeZone.getTimeZone("GMT+8")); // 设置时区为东八区
            String endTimeString = sdf.format(endTime);
            matchQueryBuilder.must(QueryBuilders.rangeQuery("publishTime")
                    .to(endTimeString));
        }
        return matchQueryBuilder;
    }

    /**
     * 构建舆情检索的开始结束时间
     *
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public BoolQueryBuilder boolQueryBuilder(BoolQueryBuilder matchQueryBuilder, Date startTime, Date endTime) {
        matchQueryBuilder = boolQueryBuilderStartTime(matchQueryBuilder, startTime);
        matchQueryBuilder = boolQueryBuilderEndTime(matchQueryBuilder, endTime);
        return matchQueryBuilder;
    }

    @Override
    public BoolQueryBuilder boolQueryBuilder(PublicOpinionEvents event) {
        BoolQueryBuilder matchQueryBuilder = QueryBuilders.boolQuery();
        return boolQueryBuilder(matchQueryBuilder, event.getSearchArea(), event.getRelatedWords(), event.getOpinionWords(), event.getExclusionWords(), event.getStartTime(), event.getEndTime());
    }

    @Override
    public BoolQueryBuilder boolQueryBuilder(List<PublicOpinionTopic> topics) {
        // 将多个BoolQueryBuilder合并在一起
        BoolQueryBuilder combinedBoolQuery = QueryBuilders.boolQuery();
        for (int i = 0; i < topics.size(); i++) {
            PublicOpinionTopic topic = topics.get(i);
            combinedBoolQuery.should(boolQueryBuilder(topic));
        }
        return combinedBoolQuery;
    }

    @Override
    public BoolQueryBuilder boolQueryBuilderOfEvent(List<PublicOpinionEvents> events) {
        // 将多个BoolQueryBuilder合并在一起
        BoolQueryBuilder combinedBoolQuery = QueryBuilders.boolQuery();
        for (int i = 0; i < events.size(); i++) {
            PublicOpinionEvents event = events.get(i);
            combinedBoolQuery.should(boolQueryBuilder(event));
        }
        return combinedBoolQuery;
    }

    @Override
    public BoolQueryBuilder boolQueryBuilder(List<PublicOpinionEvents> events, List<PublicOpinionTopic> topics) {
// 将多个BoolQueryBuilder合并在一起
        BoolQueryBuilder combinedBoolQuery = QueryBuilders.boolQuery();
        for (int i = 0; i < events.size(); i++) {
            PublicOpinionEvents event = events.get(i);
            combinedBoolQuery.should(boolQueryBuilder(event));
        }
        for (int i = 0; i < topics.size(); i++) {
            PublicOpinionTopic topic = topics.get(i);
            combinedBoolQuery.should(boolQueryBuilder(topic));
        }
        return combinedBoolQuery;
    }


    @Override
    public BoolQueryBuilder boolQueryBuilder(WarningRule rule) {

        BoolQueryBuilder queryBuilder = boolQueryBuilder(null, rule.getSearchArea(), rule.getRelatedWords(), rule.getOpinionWords(), rule.getExclusionWords());
        if(rule.getEmotion()!=null&&rule.getEmotion().size()>0){
            for (String emotion:rule.getEmotion()) {
                if(emotion.equals("positive")){
                    queryBuilder.must(QueryBuilders.termQuery("ispositive", 1));
                }else if(emotion.equals("neutral")){
                    queryBuilder.must(QueryBuilders.termQuery("isneutral", 1));
                }else if(emotion.equals("negative")){
                    queryBuilder.must(QueryBuilders.termQuery("isnegative", 1));
                }
            }
        }
        if(rule.getMediaType()!=null&&rule.getMediaType().size()>0){
            queryBuilder.must(QueryBuilders.termsQuery("carrie", rule.getMediaType()));
        }
        return queryBuilder;
    }
}
